package com.myself.community.controller;

import com.google.code.kaptcha.Producer;
import com.myself.community.annotation.LoginRequired;
import com.myself.community.entity.User;
import com.myself.community.service.FollowService;
import com.myself.community.service.LikeService;
import com.myself.community.service.UserService;
import com.myself.community.utils.Code;
import com.myself.community.utils.CommunityUtil;
import com.myself.community.utils.HostHolder;
import com.myself.community.utils.MailClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;

@Slf4j
@Controller
@RequestMapping("/user")
public class UserController {

    @Value("${community.path.upload}")
    private String uploadPath;

    @Value("${community.path.domain}")
    private String domain;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Autowired
    private UserService userService;

    @Autowired
    private HostHolder hostHolder;

    @Autowired
    private Producer kaptchaProducer;

    @Autowired
    private MailClient mailClient;//邮件客户端

    @Autowired
    private TemplateEngine templateEngine;//模板引擎

    @Autowired
    private LikeService likeService;

    @Autowired
    private FollowService followService;

    /**
     * 返回账号设置页面
     * @return
     */
    @LoginRequired
    @GetMapping("/setting")
    public String getSettingPage() {
        return "/site/setting";
    }

    /**
     * 更新用户头像
     * @param headerImage
     * @param model
     * @return
     */
    @LoginRequired
    @PostMapping("/upload")
    public String uploadHeader(MultipartFile headerImage, Model model) {
        //文件名为空
        if (headerImage == null) {
            model.addAttribute("error", "您还没有选择图片!");
            return "/site/setting";
        }
        //获取文件后缀格式
        String fileName = headerImage.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        if (StringUtils.isBlank(suffix)) {
            model.addAttribute("error", "文件的格式不正确!");
            return "/site/setting";
        }

        // 生成随机文件名
        fileName = CommunityUtil.generateUUID() + suffix;

        // 确定文件存放的路径
        File dest = new File(uploadPath + "/");//项目路径下的project_image
        if(!dest.exists())//若不存在此目录，则需要创建
            dest.mkdirs();
        String path=dest.getAbsolutePath();//获得绝对路径

        try {
            // 存储文件
            headerImage.transferTo(new File(path+"/"+fileName));
        } catch (IOException e) {
            log.error("上传文件失败: " + e.getMessage());
            throw new RuntimeException("上传文件失败,服务器发生异常!", e);
        }

        // 更新当前用户的头像的路径(web访问路径)
        // http://localhost:80/community/user/header/xxx.png
        User user = hostHolder.getUser();
        String headerUrl = domain + contextPath + "/user/header/" + fileName;
        userService.updateHeader(user.getId(), headerUrl);

        return "redirect:/index";
    }

    /**
     * 读取头像
     * @param fileName
     * @param response
     */
    @GetMapping("/header/{fileName}")
    public void getHeader(@PathVariable("fileName") String fileName, HttpServletResponse response) {
        // 服务器存放路径
        fileName = uploadPath + "/" + fileName;
        // 文件后缀
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        // 响应类型：图片
        response.setContentType("image/" + suffix);
        try (
                FileInputStream fis = new FileInputStream(fileName);
                OutputStream os = response.getOutputStream();
        ) {
            byte[] buffer = new byte[1024];
            int b = 0;
            while ((b = fis.read(buffer)) != -1) {
                os.write(buffer, 0, b);
            }
        } catch (IOException e) {
            log.error("读取头像失败: " + e.getMessage());
        }
    }

    /**
     * 修改密码
     * @param oldPassword
     * @param newPassword
     * @param model
     * @return
     */
    @PostMapping("/updatep")
    public String updatePassword(String oldPassword,String newPassword,Model model){
        Map<String, Object> map = userService.updatePassword(oldPassword, newPassword);
        if(map==null || map.isEmpty()){
            //修改成功
            //退出登录
            return "redirect:/logout";
        }
        else
        {
            //修改失败
            model.addAttribute("oldPasswordMsg",map.get("oldPasswordMsg"));
            model.addAttribute("newPasswordMsg",map.get("newPasswordMsg"));
            return "/site/setting";
        }
    }

    /**
     * 跳转忘记密码页面
     * @return
     */
    @GetMapping("/forget")
    public String getForgetPage(){
        return "/site/forget";
    }

    /**
     * 发送验证码用于找回密码
     * @param email
     * @param session
     * @return
     */
    @GetMapping("/sendcodeMsg/{email}")
    @ResponseBody
    public String sendcodeMsg(@PathVariable String email,HttpSession session){
        //log.info("laile");
        //生成验证码
        String text = kaptchaProducer.createText();

        // 将验证码存入session
        session.setAttribute("code", text);

        ////获取Thymeleaf模版
        Context context = new Context();

        //构建接收邮件参数
        context.setVariable("email", email);
        //构建验证码参数
        context.setVariable("code",text);

        //将模版内容转为字符串类型并将参数传入
        String content = templateEngine.process("/mail/forget", context);

        //发送激活邮件
        mailClient.sendMail(email, "找回密码", content);

        return "OK";
    }

    /**
     * 忘记密码，重置密码
     * @param email
     * @param code
     * @param password
     * @return
     */
    @PostMapping("/forget")
    public String forgetPassword(String email,String code,String password,HttpSession session,Model model){
        //log.info(email);
        //得到生成的验证码
        String code1 = (String) session.getAttribute("code");

        //session中的验证码为空、输入的验证码为空、忽略大小写比较不等时错误
        if (StringUtils.isBlank(code1) || StringUtils.isBlank(code) || !code1.equalsIgnoreCase(code)) {
            model.addAttribute("codeMsg", "验证码不正确!");
            return "/site/forget";
        }

        //更新密码
        Map<String, Object> map = userService.forgetPassword(email, password);
        if(map.isEmpty())
            //成功
            return "/site/login";
        else
        {
            //修改失败
            model.addAttribute("emailMsg",map.get("emailMsg"));
            model.addAttribute("passwordMsg",map.get("passwordMsg"));
            return "/site/forget";
        }
    }


    /**
     * 查询用户主页
     * @param userId
     * @param model
     * @return
     */
    @GetMapping("/profile/{userId}")
    public String getProfilePage(@PathVariable("userId") int userId, Model model) {
        //获取需要查看主页的用户对象
        User user = userService.findUserById(userId);
        if (user == null) {
            throw new RuntimeException("该用户不存在!");
        }

        // 用户
        model.addAttribute("user", user);
        // 点赞数量
        int likeCount = likeService.findUserLikeCount(userId);
        model.addAttribute("likeCount", likeCount);

        // 关注数量
        long followeeCount = followService.findFolloweeCount(userId, Code.ENTITY_TYPE_USER);
        model.addAttribute("followeeCount", followeeCount);
        // 粉丝数量
        long followerCount = followService.findFollowerCount(Code.ENTITY_TYPE_USER, userId);
        model.addAttribute("followerCount", followerCount);
        // 是否已关注
        boolean hasFollowed = false;
        if (hostHolder.getUser() != null) {
            hasFollowed = followService.hasFollowed(hostHolder.getUser().getId(), Code.ENTITY_TYPE_USER, userId);
        }
        model.addAttribute("hasFollowed", hasFollowed);

        return "/site/profile";
    }



}
